package org.chartsy.srift; import com.tictactec.ta.lib.Core; import com.tictactec.ta.lib.MAType; import com.tictactec.ta.lib.MInteger; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.Stroke; import java.text.DecimalFormat; import java.util.LinkedHashMap; import org.chartsy.main.ChartFrame; import org.chartsy.main.chart.Indicator; import org.chartsy.main.data.DataItem; import org.chartsy.main.data.Dataset; import org.chartsy.main.utils.DefaultPainter; import org.chartsy.main.utils.Range; import org.chartsy.main.utils.SerialVersion; import org.chartsy.main.utils.StrokeGenerator; import org.chartsy.talib.TaLibInit; import org.chartsy.talib.TaLibUtilities; import org.openide.nodes.AbstractNode; /** * * @author Viorel */ public class SRIFT extends Indicator { private static final long serialVersionUID = SerialVersion.APPVERSION; public static final String SRIFT = "srift"; private IndicatorProperties properties; public SRIFT() { super(); properties = new IndicatorProperties(); } public @Override String getName() { return "Smoothed RSI Inverse Fisher Transform"; } public @Override String getLabel() { return properties.getLabel(); } public @Override String getPaintedLabel(ChartFrame cf) { return getLabel(); } public @Override Indicator newInstance() { return new SRIFT(); } public @Override LinkedHashMap getHTML(ChartFrame cf, int i) { LinkedHashMap ht = new LinkedHashMap(); DecimalFormat df = new DecimalFormat("#,##0.00"); double[] values = getValues(cf, i); String[] labels = {"SRIFT:"}; ht.put(getLabel(), " "); if (values.length > 0) { Color[] colors = getColors(); for (int j = 0; j < values.length; j++) { ht.put(getFontHTML(colors[j], labels[j]), getFontHTML(colors[j], df.format(values[j]))); } } return ht; } public @Override Range getRange(ChartFrame cf) { return new Range(-1, 101); } public @Override void paint(Graphics2D graphics, ChartFrame chartFrame, Rectangle bounds) { Dataset visibleDataset = visibleDataset(chartFrame, SRIFT); if (visibleDataset != null) { if (maximized) { Range range = getRange(chartFrame); DefaultPainter.line( graphics, chartFrame, range, bounds, visibleDataset, properties.getColor(), properties.getStroke()); // paint line } } } public @Override void calculate() { Dataset initial = getDataset(); if (initial != null && !initial.isEmpty()) { int rsiPeriod = properties.getRsiPeriod(); int emaPeriod = properties.getEmaPeriod(); int svePeriod = properties.getSvePeriod(); Dataset sveRaindowWeighted = sveRainbowWeightedDataset(initial, svePeriod); Dataset xInput = xInputDataset(rsiDataset(sveRaindowWeighted, rsiPeriod)); Dataset ema1 = Dataset.EMA(xInput, emaPeriod); Dataset ema2 = Dataset.EMA(ema1, emaPeriod); Dataset diff = Dataset.DIFF(ema1, ema2); Dataset zlema = Dataset.SUM(ema1, diff); Dataset calculated = getInverseFisher(zlema); addDataset(SRIFT, calculated); } } public @Override boolean hasZeroLine() { return false; } public @Override boolean getZeroLineVisibility() { return false; } public @Override Color getZeroLineColor() { return null; } public @Override Stroke getZeroLineStroke() { return null; } public @Override boolean hasDelimiters() { return true; } public @Override boolean getDelimitersVisibility() { return true; } public @Override double[] getDelimitersValues() { return new double[] { 30d, 50d, 70d }; } public @Override Color getDelimitersColor() { return new Color(0xbbbbbb); } public @Override Stroke getDelimitersStroke() { return StrokeGenerator.getStroke(1); } public @Override Color[] getColors() { return new Color[] { properties.getColor() }; } public @Override double[] getValues(ChartFrame chartFrame) { Dataset visibleDataset = visibleDataset(chartFrame, SRIFT); if (visibleDataset != null) return new double[] { visibleDataset.getLastClose() }; return new double[] {}; } public @Override double[] getValues(ChartFrame chartFrame, int i) { Dataset visibleDataset = visibleDataset(chartFrame, SRIFT); if (visibleDataset != null) return new double[] { visibleDataset.getCloseAt(i) }; return new double[] {}; } public @Override boolean getMarkerVisibility() { return properties.getMarker(); } public @Override AbstractNode getNode() { return new IndicatorNode(properties); } public @Override Double[] getPriceValues(ChartFrame cf) { return new Double[] { new Double(10), new Double(30), new Double(50), new Double(70), new Double(90) }; } private Dataset getInverseFisher(Dataset initial) { int count = 0; if (initial != null && !initial.isEmpty()) count = initial.getItemsCount(); Dataset result = Dataset.EMPTY(count); for (int i = 0; i < count; i++) { if (initial.getDataItem(i) != null) { long time = initial.getTimeAt(i); double close = initial.getCloseAt(i); double invfish = ((Math.exp(2 * close) - 1) / (Math.exp(2 * close) + 1) + 1) * 50; result.setDataItem(i, new DataItem(time, invfish)); } } return result; } private Dataset xInputDataset(Dataset initial) { int count = 0; if (initial != null && !initial.isEmpty()) count = initial.getItemsCount(); Dataset result = Dataset.EMPTY(count); for (int i = 0; i < count; i++) { if (initial.getDataItem(i) != null) { long time = initial.getTimeAt(i); double close = initial.getCloseAt(i); double x = 0.1D * (close - 50); result.setDataItem(i, new DataItem(time, x)); } } return result; } private Dataset rsiDataset(Dataset initial, int period) { int count = initial.getItemsCount(); Dataset result = Dataset.EMPTY(count); for (int i = period; i < count; i++) { double adva = 0; double decl = 0; double currentRSI; for (int j = 0; j < period; j++) { if (initial.getCloseAt(i-j) > initial.getCloseAt(i-j-1)) { adva += initial.getCloseAt(i-j) - initial.getCloseAt(i-j-1); } else if (initial.getCloseAt(i-j) < initial.getCloseAt(i-j-1)) { decl += initial.getCloseAt(i-j-1) - initial.getCloseAt(i-j); } } if (decl == 0) { currentRSI = 100000D; } else { currentRSI = (double) adva/decl + 1; } result.setDataItem(i, new DataItem(initial.getTimeAt(i), (100 - 100/currentRSI))); } return result; } private Dataset wmaDataset(Dataset initial, int period) { int count = 0; if (initial != null && !initial.isEmpty()) count = initial.getItemsCount(); double[] output = new double[count]; MInteger outBegIdx = new MInteger(); MInteger outNbElement = new MInteger(); Core core = TaLibInit.getCore(); int lookback = core.movingAverageLookback(period, MAType.Wma); core.wma(0, count-1, initial.getCloseValues(), period, outBegIdx, outNbElement, output); output = TaLibUtilities.fixOutputArray(output, lookback); Dataset wma = Dataset.EMPTY(initial.getItemsCount()); for (int i = 0; i < output.length; i++) wma.setDataItem(i, new DataItem(initial.getTimeAt(i), output[i])); return wma; } private Dataset sveRainbowWeightedDataset(Dataset initial, int period) { int count = 0; if (initial != null && !initial.isEmpty()) count = initial.getItemsCount(); Dataset level01 = wmaDataset(initial, period); Dataset level02 = wmaDataset(level01, period); Dataset level03 = wmaDataset(level02, period); Dataset level04 = wmaDataset(level03, period); Dataset level05 = wmaDataset(level04, period); Dataset level06 = wmaDataset(level05, period); Dataset level07 = wmaDataset(level06, period); Dataset level08 = wmaDataset(level07, period); Dataset level09 = wmaDataset(level08, period); Dataset level10 = wmaDataset(level09, period); Dataset result = Dataset.EMPTY(count); for (int i = 0; i < count; i++) { if (level10.getDataItem(i) != null) { long time = level10.getTimeAt(i); double value01 = 5 * level01.getCloseAt(i); double value02 = 4 * level02.getCloseAt(i); double value03 = 3 * level03.getCloseAt(i); double value04 = 2 * level04.getCloseAt(i); double value05 = level05.getCloseAt(i); double value06 = level06.getCloseAt(i); double value07 = level07.getCloseAt(i); double value08 = level08.getCloseAt(i); double value09 = level09.getCloseAt(i); double value10 = level10.getCloseAt(i); double sveRW = (value01 + value02 + value03 + value04 + value05 + value06 + value07 + value08 + value09 + value10) / 20; result.setDataItem(i, new DataItem(time, sveRW)); } } return initial; } }